package com.google.gwt.mobile.widgets.event;

import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.mobile.widgets.utils.Point;
import com.google.gwt.mobile.widgets.utils.Utils;
import com.google.gwt.user.client.Event;

/**
 * The Class TouchControllerMobile.
 */
public class TouchControllerMobile extends TouchController {

  private boolean _touchMoving = false;

  @Override
  protected void registerClickListener() {
    super.registerClickListener();
    if (_dragStartListener == null) {
      _dragStartListener = Utils.addEventListener(_source.getElement(), "touchstart", true, this);
      _dragMoveListener = Utils.addEventListener(_source.getElement(), "touchmove", true, this);
      _dragEndListener = Utils.addEventListener(_source.getElement(), "touchend", true, this);
    }
  }

  @Override
  protected void unregisterClickListener() {
    super.unregisterClickListener();
    if (_dragStartListener != null) {
      Utils.removeEventListener(_source.getElement(), "touchstart", true, _dragStartListener);
      Utils.removeEventListener(_source.getElement(), "touchmove", true, _dragMoveListener);
      Utils.removeEventListener(_source.getElement(), "touchend", true, _dragEndListener);
      _dragStartListener = _dragMoveListener = _dragEndListener = null;
    }
  }

  /**
   * On touch start.
   * 
   * @param e the e
   */
  public void onTouchStart(final TouchEvent e) {
    EventTarget target = e.getEventTarget();
    boolean preventDefault = true;
    if (Element.is(target)) {
      Element ele = Element.as(target);
      // INPUT element will not get focus if default action is prevented.
      if (Utils.isHtmlFormControl(ele)) {
        ele.focus();
        preventDefault = false;
      }
    }
    if (preventDefault) {
      e.preventDefault(); // prevent default action of selecting text
      e.stopPropagation();
    }
    // TODO: multi-touch
    onStart(e, new Point(e.touches().get(0).getClientX(), e.touches().get(0).getClientY()));
  }

  /**
   * On touch move.
   * 
   * @param e the e
   */
  public void onTouchMove(final TouchEvent e) {
    e.preventDefault();
    e.stopPropagation();
    _touchMoving = true;
    onMove(e, new Point(e.touches().get(0).getClientX(), e.touches().get(0).getClientY()));
  }

  /**
   * On touch end.
   * 
   * @param e the e
   */
  public void onTouchEnd(final TouchEvent e) {
    e.preventDefault();
    e.stopPropagation();
    if (!_touchMoving) {
      fireClick(e);
    }
    _touchMoving = false;
    onEnd(e, new Point(e.changedTouches().get(0).getClientX(), e.changedTouches().get(0)
        .getClientY()));
  }

  /*
   * (non-Javadoc)
   * 
   * @see
   * com.google.gwt.mobile.widgets.event.TouchController#onBrowserEvent
   * (com.google.gwt.user.client.Event)
   */
  @Override
  public void onBrowserEvent(final Event e) {
    String type = e.getType();
    if (type.equals("touchstart")) {
      onTouchStart((TouchEvent) e);
    } else if (type.equals("touchmove")) {
      onTouchMove((TouchEvent) e);
    } else if (type.equals("touchend")) {
      onTouchEnd((TouchEvent) e);
    } else {
      super.onBrowserEvent(e);
    }
  }

  private native void fireClick(Event e) /*-{
		var x = e.changedTouches[0].pageX;
		var y = e.changedTouches[0].pageY;

		var theTarget = $doc.elementFromPoint(x, y);
		if (theTarget.nodeType == 3)
			theTarget = theTarget.parentNode;

		var theEvent = $doc.createEvent('MouseEvents');
		theEvent.initEvent('click', true, true);
		theTarget.dispatchEvent(theEvent);
  }-*/;

}
